package com.meiyuetao.myt.purchase.web.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import lab.s2jh.bpm.service.ActivitiService;
import lab.s2jh.core.annotation.MetaData;
import lab.s2jh.core.pagination.GroupPropertyFilter;
import lab.s2jh.core.pagination.PropertyFilter;
import lab.s2jh.core.pagination.PropertyFilter.MatchType;
import lab.s2jh.core.security.AuthContextHolder;
import lab.s2jh.core.service.BaseService;
import lab.s2jh.core.service.Validation;
import lab.s2jh.core.web.view.OperationResult;

import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.rest.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.meiyuetao.myt.core.constant.StorageModeEnum;
import com.meiyuetao.myt.core.constant.VoucherTypeEnum;
import com.meiyuetao.myt.core.service.VoucherNumGenerateService;
import com.meiyuetao.myt.core.web.MytBaseController;
import com.meiyuetao.myt.finance.entity.TradeReceiptDetail;
import com.meiyuetao.myt.md.entity.Commodity;
import com.meiyuetao.myt.md.service.CommodityService;
import com.meiyuetao.myt.purchase.entity.PurchaseOrder;
import com.meiyuetao.myt.purchase.entity.PurchaseOrderDetail;
import com.meiyuetao.myt.purchase.entity.PurchaseReceipt;
import com.meiyuetao.myt.purchase.entity.PurchaseReceiptDetail;
import com.meiyuetao.myt.purchase.service.PurchaseOrderService;
import com.meiyuetao.myt.purchase.service.PurchaseReceiptDetailService;
import com.meiyuetao.myt.purchase.service.PurchaseReceiptService;
import com.meiyuetao.myt.purchase.service.SupplierService;
import com.meiyuetao.myt.sale.entity.SaleDelivery;
import com.meiyuetao.myt.sale.service.SaleDeliveryService;
import com.meiyuetao.myt.stock.entity.StorageLocation;
import com.meiyuetao.myt.stock.service.StorageLocationService;

@MetaData("采购订单")
public class PurchaseOrderController extends MytBaseController<PurchaseOrder, Long> {

    private final Logger logger = LoggerFactory.getLogger(PurchaseOrderController.class);

    @Autowired
    private PurchaseOrderService purchaseOrderService;
    @Autowired
    private SupplierService supplierService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private CommodityService commodityService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private PurchaseReceiptDetailService purchaseReceiptDetailService;
    @Autowired
    private PurchaseReceiptService purchaseReceiptService;
    @Autowired
    private SaleDeliveryService saleDeliveryService;
    @Autowired
    private StorageLocationService storageLocationService;
    @Autowired
    private ActivitiService activitiService;

    @Autowired
    private VoucherNumGenerateService voucherNumGenerateService;

    @Override
    protected BaseService<PurchaseOrder, Long> getEntityService() {
        return purchaseOrderService;
    }

    /**
     * 获取计划入库时间已到还未入库的采购
     * 
     * @return
     */
    public HttpHeaders getInStockWarningList() {
        // 计划入库时间已到还未入库的
        GroupPropertyFilter groupFilter = GroupPropertyFilter.buildDefaultAndGroupFilter();
        groupFilter = GroupPropertyFilter.buildDefaultAndGroupFilter();
        groupFilter.append(new PropertyFilter(MatchType.LE, "planReceiptDate", new Date()));// 计划入库时间已到
        groupFilter.append(new PropertyFilter(MatchType.NU, "receiptAuditDate", true));// 没有入库的
        groupFilter.append(new PropertyFilter(MatchType.NU, "redwordDate", true));// 没有红冲的
        List<PurchaseOrder> purchaseOrders = purchaseOrderService.findByFilters(groupFilter);
        setModel(buildPageResultFromList(purchaseOrders));
        return buildDefaultHttpHeaders();
    }

    @Override
    protected void checkEntityAclPermission(PurchaseOrder entity) {
        // TODO Add acl check code logic
    }

    protected void setupDetachedBindingEntity(Long id) {
        bindingEntity = getEntityService().findDetachedOne(id, "purchaseOrderDetails");
    }

    @Override
    @MetaData("查询")
    public HttpHeaders findByPage() {
        return super.findByPage();
    }

    public Map<String, Object> getTaskVariables() {
        Map<String, Object> variables = taskService.getVariables(this.getRequiredParameter("taskId"));
        if (logger.isDebugEnabled()) {
            for (Map.Entry<String, Object> me : variables.entrySet()) {
                logger.debug("{} - {}", me.getKey(), me.getValue());
            }
        }
        return variables;
    }

    public String isDisallowChargeAgainst() {
        GroupPropertyFilter groupPropertyFilter = GroupPropertyFilter.buildDefaultAndGroupFilter();
        groupPropertyFilter.forceAnd(new PropertyFilter(MatchType.NU, "purchaseOrderDetail", false));
        groupPropertyFilter.forceAnd(new PropertyFilter(MatchType.EQ, "purchaseOrderDetail.purchaseOrder", bindingEntity));
        List<PurchaseReceiptDetail> purchaseReceiptDetails = purchaseReceiptDetailService.findByFilters(groupPropertyFilter);
        if (purchaseReceiptDetails.size() > 0) {
            return "已收货，不能红冲";
        }
        return null;
    }

    @Override
    @MetaData("保存")
    public HttpHeaders doSave() {
        if (bindingEntity.isNew()) {
            List<PurchaseOrderDetail> purchaseOrderDetails = bindingEntity.getPurchaseOrderDetails();
            for (PurchaseOrderDetail purchaseOrderDetail : purchaseOrderDetails) {
                purchaseOrderDetail.setPurchaseOrder(bindingEntity);
            }
        }
        return super.doSave();
    }

    public void prepareBpmNew() {
        String clone = this.getParameter("clone");
        if (BooleanUtils.toBoolean(clone)) {
            bindingEntity.resetCommonProperties();
        } else {
            bindingEntity = new PurchaseOrder();
        }
        bindingEntity.setVoucher(voucherNumGenerateService.getVoucherNumByType(VoucherTypeEnum.JHD));
        bindingEntity.setVoucherDate(new Date());
        bindingEntity.setVoucherUser(getLogonUser());
        bindingEntity.setVoucherDepartment(getLogonUser().getDepartment());

    }

    @MetaData("采购订单创建初始化")
    public HttpHeaders bpmNew() {
        return buildDefaultHttpHeaders("bpmInput");
    }

    @MetaData("采购订单保存")
    public HttpHeaders bpmSave() {
        Set<StorageLocation> storageLocations = Sets.newHashSet();
        for (PurchaseOrderDetail pod : bindingEntity.getPurchaseOrderDetails()) {
            storageLocations.add(pod.getStorageLocation());
        }
        Validation.isTrue(storageLocations.size() == 1, "同一采购单商品库存地必须一致");
        Boolean flag = true;
        for (PurchaseOrderDetail pod : bindingEntity.getPurchaseOrderDetails()) {

            StorageLocation storageLocation = storageLocationService.findOne(pod.getStorageLocation().getId());
            if (!bindingEntity.getStorageMode().equals(storageLocation.getStorageMode())) {
                flag = false;
                break;
            }
        }
        Validation.isTrue(flag, "采购单库存模式和商品库存地的模式不一致");
        if (StorageModeEnum.SA.equals(bindingEntity.getStorageMode())) {
            SaleDelivery saleDelivery = bindingEntity.getSaleDelivery();
            if (bindingEntity.getSaleDelivery() != null) {
                saleDelivery = saleDeliveryService.findOne(bindingEntity.getSaleDelivery().getId());
            }
            if (saleDelivery == null || !StorageModeEnum.SA.equals(saleDelivery.getStorageMode())) {
                Validation.isTrue(false, "代发采购订单，必须关联代发模式的销售单");
            }
            Validation.isTrue(saleDelivery.getAuditDate() != null, "销售单还未审核");

        }
        Map<String, Object> variables = Maps.newHashMap();
        String submitToAudit = this.getParameter("submitToAudit");
        if (BooleanUtils.toBoolean(submitToAudit)) {
            bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("提交"));
            bindingEntity.setSubmitDate(new Date());
        }

        List<PurchaseOrderDetail> purchaseOrderDetails = bindingEntity.getPurchaseOrderDetails();
        for (PurchaseOrderDetail purchaseOrderDetail : purchaseOrderDetails) {
            purchaseOrderDetail.setPurchaseOrder(bindingEntity);
        }
        if (StringUtils.isBlank(bindingEntity.getTitle())) {
            Commodity commodity = commodityService.findOne(purchaseOrderDetails.get(0).getCommodity().getId());
            String commodityTitle = commodity.getTitle();
            commodityTitle = StringUtils.substring(commodityTitle, 0, 30);
            bindingEntity.setTitle(commodityTitle + "...等" + purchaseOrderDetails.size() + "项商品");
        }

        if (bindingEntity.isNew()) {
            purchaseOrderService.bpmCreate(bindingEntity, variables);
            setModel(OperationResult.buildSuccessResult("采购订单创建完成，并同步启动处理流程", bindingEntity));
        } else {
            purchaseOrderService.bpmUpdate(bindingEntity, this.getRequiredParameter("taskId"), variables);
            setModel(OperationResult.buildSuccessResult("采购订单任务提交完成", bindingEntity));
        }
        return buildDefaultHttpHeaders();
    }

    @MetaData("采购订单定价")
    public HttpHeaders bpmPrice() {
        Set<StorageLocation> storageLocations = Sets.newHashSet();
        for (PurchaseOrderDetail pod : bindingEntity.getPurchaseOrderDetails()) {
            storageLocations.add(pod.getStorageLocation());
        }
        Validation.isTrue(storageLocations.size() == 1, "同一采购单商品库存地必须一致");
        Boolean flag = true;
        for (PurchaseOrderDetail pod : bindingEntity.getPurchaseOrderDetails()) {

            StorageLocation storageLocation = storageLocationService.findOne(pod.getStorageLocation().getId());
            if (!bindingEntity.getStorageMode().equals(storageLocation.getStorageMode())) {
                flag = false;
                break;
            }
        }
        Validation.isTrue(flag, "采购单库存模式和商品库存地的模式不一致");
        Map<String, Object> variables = Maps.newHashMap();
        List<PurchaseOrderDetail> purchaseOrderDetails = bindingEntity.getPurchaseOrderDetails();
        for (PurchaseOrderDetail purchaseOrderDetail : purchaseOrderDetails) {
            purchaseOrderDetail.setPurchaseOrder(bindingEntity);
        }
        bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("定价"));
        purchaseOrderService.bpmUpdate(bindingEntity, this.getRequiredParameter("taskId"), variables);
        setModel(OperationResult.buildSuccessResult("采购订单定价完成", bindingEntity));
        return buildDefaultHttpHeaders();
    }

    @MetaData("一线审核")
    public HttpHeaders bpmLevel1Audit() {
        Map<String, Object> variables = Maps.newHashMap();
        variables.put("auditLevel1Time", new Date());
        variables.put("auditLevel1User", AuthContextHolder.getAuthUserPin());
        Boolean auditLevel1Pass = new Boolean(getRequiredParameter("auditLevel1Pass"));
        variables.put("auditLevel1Pass", auditLevel1Pass);
        variables.put("auditLevel1Explain", getParameter("auditLevel1Explain"));
        bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("审核"));
        if (!auditLevel1Pass) {
            bindingEntity.setSubmitDate(null);
        }
        bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("一审"));
        purchaseOrderService.bpmLevel1Audit(bindingEntity, this.getRequiredParameter("taskId"), variables);
        setModel(OperationResult.buildSuccessResult("采购订单一线审核完成", bindingEntity));
        return buildDefaultHttpHeaders();
    }

    @MetaData("二线审核")
    public HttpHeaders bpmLevel2Audit() {
        Map<String, Object> variables = Maps.newHashMap();
        variables.put("auditLevel2Time", new Date());
        variables.put("auditLevel2User", AuthContextHolder.getAuthUserPin());
        Boolean auditLevel2Pass = new Boolean(getRequiredParameter("auditLevel2Pass"));
        variables.put("auditLevel2Pass", auditLevel2Pass);
        variables.put("auditLevel2Explain", getParameter("auditLevel2Explain"));
        if (!auditLevel2Pass) {
            bindingEntity.setSubmitDate(null);
        }
        bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("二审"));
        purchaseOrderService.bpmLevel2Audit(bindingEntity, this.getRequiredParameter("taskId"), variables);
        setModel(OperationResult.buildSuccessResult("采购订单二线审核完成", bindingEntity));
        return buildDefaultHttpHeaders();
    }

    @MetaData("采购订单付款界面显示")
    public HttpHeaders bpmPayInput() {
        return buildDefaultHttpHeaders("bpmPay");
    }

    private List<TradeReceiptDetail> tradeReceiptDetails = new ArrayList<TradeReceiptDetail>();
    private List<PurchaseReceipt> bpmReceipts = new ArrayList<PurchaseReceipt>();

    @MetaData("(预)付款任务")
    public HttpHeaders bpmPay() {
        bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("付款"));
        purchaseOrderService.bpmPay(bindingEntity, this.getRequiredParameter("taskId"), tradeReceiptDetails);
        setModel(OperationResult.buildSuccessResult("采购(预)付款任务处理完成", bindingEntity));
        return buildDefaultHttpHeaders();
    }

    @MetaData("保存卖家发货信息")
    public HttpHeaders bpmDelivery() {
        bindingEntity.setDeliveryTime(new Date());
        bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("录入物流"));
        purchaseOrderService.bpmDelivery(bindingEntity, this.getRequiredParameter("taskId"));
        setModel(OperationResult.buildSuccessResult("录入卖家发货信息完成", bindingEntity));
        return buildDefaultHttpHeaders();
    }

    @MetaData("到付付款")
    public HttpHeaders bpmLaterPay() {
        Map<String, Object> variables = Maps.newHashMap();
        variables.put("laterPayDate", getParameter("laterPayDate"));
        variables.put("laterPayMemo", getParameter("laterPayMemo"));
        purchaseOrderService.bpmUpdate(bindingEntity, this.getRequiredParameter("taskId"), variables);
        setModel(OperationResult.buildSuccessResult("到付付款完成", bindingEntity));
        return buildDefaultHttpHeaders();
    }

    @MetaData("入库审核")
    public HttpHeaders bpmReceiptAudit() {
        bindingEntity.setReceiptAuditDate(new Date());
        bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("入库审核"));
        purchaseOrderService.bpmUpdate(bindingEntity, this.getRequiredParameter("taskId"), null);
        setModel(OperationResult.buildSuccessResult("入库审核完成", bindingEntity));
        return buildDefaultHttpHeaders();
    }

    @MetaData("行项数据")
    public HttpHeaders purchaseOrderDetails() {
        List<PurchaseOrderDetail> purchaseOrderDetails = bindingEntity.getPurchaseOrderDetails();
        if (BooleanUtils.toBoolean(getParameter("clone"))) {
            for (PurchaseOrderDetail purchaseOrderDetail : purchaseOrderDetails) {
                purchaseOrderDetail.resetCommonProperties();
            }
        }
        setModel(buildPageResultFromList(purchaseOrderDetails));
        return buildDefaultHttpHeaders();
    }

    public HttpHeaders doRedword() {
        Assert.isTrue(bindingEntity.getRedwordDate() == null);
        bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("红冲"));
        purchaseOrderService.redword(bindingEntity);
        setModel(OperationResult.buildSuccessResult("红冲完成"));
        return buildDefaultHttpHeaders();
    }

    public List<TradeReceiptDetail> getTradeReceiptDetails() {
        return tradeReceiptDetails;
    }

    public void setTradeReceiptDetails(List<TradeReceiptDetail> tradeReceiptDetails) {
        this.tradeReceiptDetails = tradeReceiptDetails;
    }

    public void prepareBpmReceiptInput() {
        bindingEntity.setVoucherUser(getLogonUser());
        bindingEntity.setVoucherDepartment(getLogonUser().getDepartment());
        GroupPropertyFilter groupPropertyFilter = GroupPropertyFilter.buildDefaultAndGroupFilter();
        groupPropertyFilter.append(new PropertyFilter(MatchType.EQ, "purchaseOrder", bindingEntity));
        List<PurchaseReceipt> purchaseReceipts = purchaseReceiptService.findByFilters(groupPropertyFilter);
        setBpmReceipts(purchaseReceipts);

    }

    @MetaData("采购收货界面显示")
    public HttpHeaders bpmReceiptInput() {
        return buildDefaultHttpHeaders("bpmReceipt");
    }

    @MetaData("采购收货")
    public HttpHeaders bpmReceipt() {
        // 判断部分收货还是已经全部收货
        String allReceipt = this.getParameter("allReceipt");
        bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("收货入库"));
        purchaseOrderService.bpmReceipt(bindingEntity, this.getRequiredParameter("taskId"), null, allReceipt);
        setModel(OperationResult.buildSuccessResult("收货入库完成", bindingEntity));
        return buildDefaultHttpHeaders();
    }

    @MetaData("完结任务")
    public HttpHeaders completeTask() {
        bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("采购入库任务完成"));
        activitiService.completeTask(this.getRequiredParameter("taskId"), null);
        setModel(OperationResult.buildSuccessResult("采购入库任务完成", bindingEntity));
        return buildDefaultHttpHeaders();
    }

    public List<PurchaseReceipt> getBpmReceipts() {
        return bpmReceipts;
    }

    public void setBpmReceipts(List<PurchaseReceipt> bpmReceipts) {
        this.bpmReceipts = bpmReceipts;
    }

}